<template>
	<div class="color-alpha-slider" :class="{ 'is-vertical': vertical }">
		<div
			ref="bar"
			class="color-alpha-slider__bar"
			:style="{
				background,
			}"
			@click="handleClick"
		></div>
		<div
			ref="thumb"
			class="color-alpha__thumb"
			:style="{ left: thumbLeft + 'px', top: thumbTop + 'px' }"
		></div>
	</div>
</template>

<script setup lang="ts">
import draggable from '../util/draggable';
import type { Nullable } from '../color-picker';
import { AlphaSliderProps } from '../color-picker';

const props = defineProps(AlphaSliderProps);

const instance = getCurrentInstance(); //当前实例
const bar = shallowRef<Nullable<HTMLElement>>(null); //管理bar
const thumb = shallowRef<Nullable<HTMLElement>>(null); //管理thumb
const thumbLeft = ref<number>(0); //管理thumb左
const thumbTop = ref<number>(0); //管理thumb右
const background = ref<any>(null); //管理background

/**
 * 监听color值
 */
watch(
	() => props.color?.get('alpha'),
	() => {
		update();
	}
);

/**
 * 监听color值
 */
watch(
	() => props.color?.value,
	() => {
		update();
	}
);

/**
 * handleClick点击事件
 * @param event
 */
const handleClick = (event: Event) => {
	const target = event.target;
	if (target !== thumb.value) {
		handleDrag(event);
	}
};

/**
 * handleDrag拖拽事件
 * @param event
 */
const handleDrag = (event: any) => {
	const ele = instance?.vnode.el as HTMLElement;
	const rect = ele.getBoundingClientRect();
	if (!props.vertical) {
		let left = event.clientX - rect.left;
		left = Math.max((thumb.value as HTMLElement).offsetWidth / 2, left);
		left = Math.min(
			left,
			rect.width - (thumb.value as HTMLElement).offsetWidth / 2
		);
		props.color?.set(
			'alpha',
			Math.round(
				((left - (thumb.value as HTMLElement).offsetWidth / 2) /
					(rect.width - (thumb.value as HTMLElement).offsetWidth)) *
					100
			)
		);
	} else {
		let top = event.clientY - rect.top;
		top = Math.max((thumb.value as HTMLElement).offsetHeight / 2, top);
		top = Math.min(
			top,
			rect.height - (thumb.value as HTMLElement).offsetHeight / 2
		);

		props.color?.set(
			'alpha',
			Math.round(
				((top - (thumb.value as HTMLElement).offsetHeight / 2) /
					(rect.height - (thumb.value as HTMLElement).offsetHeight)) *
					100
			)
		);
	}
};

/**
 * update更新事件
 */
const update = () => {
	thumbLeft.value = getThumbLeft();
	thumbTop.value = getThumbTop();
	background.value = getBackground();
};

/**
 * 获取Thumb左侧
 */
const getThumbLeft = (): number => {
	if (props.vertical) return 0;
	const ele = instance?.vnode.el;
	const alpha = props.color?.get('alpha');

	if (!ele) return 0;
	return Math.round(
		(alpha * (ele.offsetWidth - (thumb.value as HTMLElement).offsetWidth / 2)) /
			100
	);
};

/**
 * 获取Thumb顶部
 */
const getThumbTop = (): number => {
	const ele = instance?.vnode.el;
	if (!props.vertical) return 0;
	const alpha = props.color?.get('alpha');
	if (!ele) return 0;
	return Math.round(
		(alpha *
			(ele.offsetHeight - (thumb.value as HTMLElement).offsetHeight / 2)) /
			100
	);
};

/**
 * 获取背景色
 */
const getBackground = () => {
	if (props.color && props.color.value) {
		const { r, g, b } = props.color.toRgb();
		return `linear-gradient(to right, rgba(${r}, ${g}, ${b}, 0) 0%, rgba(${r}, ${g}, ${b}, 1) 100%)`;
	}
	return null;
};

defineExpose({ update });
onMounted(() => {
	const dragConfig = {
		drag: (event: any) => {
			handleDrag(event);
		},
		end: (event: any) => {
			handleDrag(event);
		},
	};
	draggable(bar.value as HTMLElement, dragConfig);
	draggable(thumb.value as HTMLElement, dragConfig);
	update();
});
</script>
